#include "ActionConsumer.h"
#include "CanAction.h"
#include "SleepAction.h"
#include "json.hpp"
#include <mutex>
#include <memory>
#include <fstream>
#include <iostream>
#include <sstream>
#include <chrono>

std::unique_ptr<IplaybackAction> createCanAction(const std::string& sigName, const int& value)
{
    return std::make_unique<CanAction>(sigName, value);
}

std::unique_ptr<IplaybackAction> createSleepAction(const uint32_t& value)
{
    return std::make_unique<SleepAction>(value);
}

std::unique_ptr<ActionConsumer> ActionConsumer::actionConsumerInstance = nullptr;

std::unique_ptr<ActionConsumer>& ActionConsumer::getInstance()
{
    static std::once_flag flag;
    std::call_once(flag, []() {
        actionConsumerInstance = std::make_unique<ActionConsumer>();
    });
    return actionConsumerInstance;
}

ActionConsumer::ActionConsumer()
    : isRunning(false), itsActionThread(nullptr), itsActions()
{

}

ActionConsumer::~ActionConsumer()
{
    if(itsActionThread)
    {
        stopPlay();
    }
}

void ActionConsumer::pushBackAction(std::unique_ptr<IplaybackAction>&& action)
{
    itsActions.emplace_back(std::move(action));
}

void ActionConsumer::parseJsonAsAction(const char* path)
{
    std::ifstream f(path);
    try {
        nlohmann::json j = nlohmann::json::parse(f);

        for (const auto& item : j) {
            int type = item["type"];
            switch(type)
            {
                case 0x00:  //CAN
                {
                    pushBackAction(createCanAction(item["sigName"], item["sigValue"]));
                    std::cout << "push can action" << item["sigName"] << " : " << item["sigValue"] << std::endl;
                    break;
                }
                case 0x01:  //SLEEP
                {
                    pushBackAction(createSleepAction(item["value"]));
                    std::cout << "push sleep action" << item["value"] << std::endl;
                    break;
                }
                default:
                {
                    break;
                }
            }
        }
    } catch (const nlohmann::json::parse_error& e) {
        std::cerr << "JSON parse error: " << e.what() << std::endl;
    }
}

void ActionConsumer::writeActionToJson()
{
    time_t now = time(nullptr);
    std::stringstream sstr;
    sstr << "C:/Users/Public/Documents/hq_" << time << ".json";
    std::ofstream file(sstr.str());

    if (file.is_open())
    {
        file << "[" << std::endl;
        for(auto i = 0; i < itsActions.size(); i++)
        {
            nlohmann::json j;
            itsActions[i]->serializeJson(j);
            file << j.dump(4);  // 使用 4 个空格缩进，增强可读性
            if(i < itsActions.size() - 1)
            {
                file << ",";    //最后一个不需要 ","
            }
            file << std::endl;
        }
        file << "]";
        file.close();
    }
    else
    {
        std::cerr << "Unable to open file" << std::endl;
    }
}

void ActionConsumer::playAction()
{
    for(auto& action : itsActions)
    {
        action->run();
        if(!isRunning)
        {
            break;
        }
    }
}

void ActionConsumer::playOnce()
{
    if(itsActionThread)
    {
        stopPlay();
    }

    if(!isRunning)
    {
        isRunning = true;
        itsActionThread = std::make_unique<std::thread>([this](){
            playAction();
            isRunning = false;
        });
    }
}

void ActionConsumer::playLoop()
{
    if(itsActionThread)
    {
        stopPlay();
    }

    if(!isRunning)
    {
        isRunning = true;
        itsActionThread = std::make_unique<std::thread>([this](){
            while(isRunning)
            {
                playAction();
            }
            isRunning = false;
        });
    }
}

void ActionConsumer::stopPlay()
{
    isRunning = false;
    if(itsActionThread && itsActionThread->joinable())
    {
        itsActionThread->join();
        itsActionThread.release();
        itsActionThread = nullptr;
    }
}

void ActionConsumer::clearActions()
{
    itsActions.clear();
    itsActions.shrink_to_fit();
    itsActions.resize(0);
}

void ActionConsumer::startRecord()
{
    clearActions();
}

void ActionConsumer::recording(const char* sigName, int value)
{
    static auto milliseconds = 0;
    auto now = std::chrono::system_clock::now();
    if(itsActions.size() == 0)
    {
        // 第一次进来
        milliseconds = std::chrono::time_point_cast<std::chrono::milliseconds>(now).time_since_epoch().count();
    }
    else
    {
        auto time = std::chrono::time_point_cast<std::chrono::milliseconds>(now).time_since_epoch().count();
        pushBackAction(createSleepAction(time - milliseconds));
        milliseconds = time;
    }
    pushBackAction(createCanAction(sigName, value));
}

void ActionConsumer::stopRecord()
{
    writeActionToJson();
}


